package com.lsa.edmonds.chap10.recursiveimg;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class RotatingSquare {

	public static void main(String s[]) {
		JFrame frame = new JFrame();
		frame.setTitle("Rotating square");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(new RotatingSquarePanel());
		frame.pack();
		frame.setSize(new Dimension(640, 480));
		frame.setVisible(true);
	}
	
	static class RotatingSquarePanel extends JPanel {
		final static double scaleFactor = 0.95;

		public RotatingSquarePanel() {
			setPreferredSize(new Dimension(640, 480));
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2 = (Graphics2D) g;
			Dimension d = getSize();

			double a2 = Math.min(d.getWidth(), d.getHeight()) * scaleFactor;
			double shifthX = (d.getWidth() - a2) / 2;
			double shifthY = (d.getHeight() - a2) / 2;
			recurseSquares(g2, new Rectangle2D.Double(shifthX, shifthY, a2, a2),
					100);
		}

		private Shape rotateRect(Rectangle2D rect, double theta) {
			double a = rect.getWidth();
			Rectangle2D rectAtOrigin = translateToOrigin(rect);
			AffineTransform tr = new AffineTransform();
			tr.translate(a * 0.5 + rect.getMinX(), a * 0.5 + rect.getMinY());
			tr.rotate(theta);
			Shape shape = tr.createTransformedShape(rectAtOrigin);
			return shape;
		}

		private void recurseSquares(Graphics2D g2, Rectangle2D area, int n) {
			Rectangle2D rect = area;
			double theta = 0.0;
			g2.setColor(Color.DARK_GRAY);
			while (n-- > 2) {
				double a = rect.getWidth();
				Shape shape = rotateRect(rect, theta);
				g2.draw(shape);

				double a2 = a * scaleFactor;
				double shift = (a - a2) / 2;
				rect.setFrame(rect.getMinX() + shift, rect.getMinY() + shift, a2,
						a2);
				theta += -(Math.PI / 4 - Math.acos(a / (Math.sqrt(2) * a2)));
			}
			if (n == 1){
				Ellipse2D circle = new Ellipse2D.Double();
				circle.setFrame(rect);
				g2.draw(circle);
			}
		}

		private Rectangle2D translateToOrigin(Rectangle2D rect) {
			Rectangle2D newRect = new Rectangle2D.Double();
			double a = rect.getWidth();
			newRect.setFrame(-a / 2, -a / 2, a, a);
			return newRect;
		}
		
//		private void recurseCirclesAndSquare(Graphics2D g2, Rectangle2D area, int n) {
//		Rectangle2D rect = area;
//		Ellipse2D circle = new Ellipse2D.Double();
//		double factor = 1;
//		final double thetaDelta = -Math.PI / 10.0;
//		// final double thetaDelta = 0.0;
//		double theta = 0.0;
//		g2.setColor(Color.blue);
//		while (n-- > 0) {
//			double a = rect.getWidth();
//			Shape shape = rotateRect(rect, theta);
//			g2.draw(shape);
//			circle.setFrame(rect);
//			g2.draw(circle);
//
//			double shift = a * (2 - Math.sqrt(2)) * 0.25 * factor;
//			double a2 = a * factor / Math.sqrt(2);
//			rect.setFrame(rect.getMinX() + shift, rect.getMinY() + shift, a2,
//					a2);
//			theta += thetaDelta;
//		}
//	}
	}
}